package cn.dada.dadarecipes.user.user.service.impl;

import cn.dada.dadarecipes.base.exception.ServiceException;
import cn.dada.dadarecipes.base.response.StatusCode;
import cn.dada.dadarecipes.user.user.pojo.dto.*;
import cn.dada.dadarecipes.user.user.pojo.vo.UserVO;
import cn.dada.dadarecipes.user.user.service.UserService;
import cn.dada.dadarecipes.user.user.mapper.UserMapper;
import cn.dada.dadarecipes.user.user.pojo.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.security.SecureRandom;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public UserVO reg(UserRegParam userRegParam) {
        log.debug("用户注册:userRegParam={}", userRegParam);
        String userName = userRegParam.getUsername();
        String phone = userRegParam.getPhone();
        // 检查用户名是否已存在
        UserVO userVO = userMapper.queryUserByUserName(userName);
        if (userVO != null) {
            throw new ServiceException(StatusCode.USERNAME_EXIST);
        }
        // 检查手机号是否已存在
        UserVO userVOByPhone = userMapper.queryUserByUserName(phone);
        if (userVOByPhone != null) {
            throw new ServiceException(StatusCode.PHONE_EXIST);
        }
        // 创建一个新的用户对象，并将必要的属性从请求参数拷贝过来。
        User user = new User();
        BeanUtils.copyProperties(userRegParam, user);
        user.setCreateTime(new Date());

        // 设置初始的粉丝数、关注数和年龄
        user.setFansNum(0L); // 默认值为0
        user.setFollowerNum(0L); // 默认值为0
        user.setAge(18); // 默认值为18
        // 插入新的用户记录到数据库。
        userMapper.insert(user);

        // 查询刚插入的用户信息，构造UserVO对象返回。
        UserVO newUserVO = userMapper.queryUserByUserName(userName);
        if (newUserVO == null) {
            // 如果重试后仍然无法获取用户信息，抛出异常。
            throw new ServiceException(StatusCode.REG_FAILED);
        }
        return newUserVO;
    }


    @Override
    public UserVO login(UserLoginParam userLoginParam, HttpSession session) {
        log.debug("用户登录:userLoginParam={}", userLoginParam);
        UserVO userVO = userMapper.queryUserByUserName(userLoginParam.getUsername());
        if (userVO == null) {
            throw new ServiceException(StatusCode.USERNAME_ERROR);
        } else if (!userVO.getPassword().equals(userLoginParam.getPassword())) {
            throw new ServiceException(StatusCode.PASSWORD_ERROR);
        }
        session.setAttribute("user", userVO.getId());
        return userVO;
    }

    @Override
    public void logout(Long id, HttpSession session) {
        log.debug("用户退出:userId={}", id);
            session.removeAttribute("user");

    }



    @Transactional
    @Override
    public void password(UserPasswordParam userPasswordParam) {
        log.debug("开始处理密码修改请求...");

        // 首先检查用户ID是否存在
        UserVO existingUser = userMapper.queryUserById(userPasswordParam.getId()).get(0);
        if (existingUser == null) {
            throw new ServiceException(StatusCode.USER_NOT_EXIST);
        }

        // 验证旧密码是否正确
        if (!userPasswordParam.getOldPassword().equals(existingUser.getPassword())) {
            throw new ServiceException(StatusCode.PASSWORD_ERROR);
        }

        // 检查新密码和确认密码是否匹配
        if (!userPasswordParam.getPassword().equals(userPasswordParam.getConfirmPassword())) {
            throw new ServiceException(StatusCode.PASSWORD_ERROR);
        }

        // 密码强度检查
        if (!isPasswordStrong(userPasswordParam.getPassword())) {
            throw new ServiceException(StatusCode.PASSWORD_STRENGTH_ERROR);
        }

        // 更新用户密码
        existingUser.setPassword(userPasswordParam.getPassword());
        existingUser.setUpdateTime(new Date());

        User user = new User();
        BeanUtils.copyProperties(existingUser, user);
        // 调用Mapper层的方法来更新用户密码
        userMapper.update(user);
    }

//    private boolean isPasswordStrong(String password) {
//        // 实现密码强度检查逻辑
//        return password.length() >= 8 && password.matches("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$");
//    }
    @Override
    public void delete(Long userId) {
        log.debug("注销用户:userId: {}", userId);
        userMapper.delete(userId);
    }

    @Override
    public void update(UserMessageEditParam userMessageEditParam) {
        log.debug("用户编辑:userMessageEditParam={}", userMessageEditParam);
        User user = new User();
        // 使用BeanUtils工具类将UserMessageEditParam对象的属性复制到User对象中
        BeanUtils.copyProperties(userMessageEditParam, user);
        // 检查是否是新用户注册（即ID为null）
        if(userMessageEditParam.getId() == null){
            // 设置默认密码
            user.setPassword("123456");
            // 设置创建时间为当前时间
            user.setCreateTime(new Date());
            userMapper.insert(user);

            // 验证用户是否成功插入数据库
            if(userMapper.queryUserByUserName(userMessageEditParam.getUsername()) == null){
                throw new ServiceException(StatusCode.REG_FAILED);
            }
        }else {
            // 对于现有用户，设置更新时间为当前时间
            user.setUpdateTime(new Date());
            userMapper.updateUser(user);

            // 验证用户是否仍然存在于数据库中
            if(userMapper.queryUserByUserName(userMessageEditParam.getUsername()) == null){
                throw new ServiceException(StatusCode.USER_NOT_EXIST);
            }
        }

    }

    @Override
    public List<UserVO> query(Long userId) {
        log.debug("查询用户:userId={}", userId);
        // 调用Mapper层的方法根据用户ID查询用户信息
        List<UserVO> userVO = userMapper.queryUserById(userId);
        return userVO;
    }


    @Override
    public void resetPassword(UserResetPassword userResetPassword) {
        // 根据手机号查询用户信息
        User user = userMapper.findByPhone(userResetPassword.getPhone());

        // 如果用户不存在，记录错误日志并抛出用户不存在异常
        if (user == null) {
            log.error("用户不存在: {}", userResetPassword.getPhone());
            throw new ServiceException(StatusCode.USER_NOT_EXIST);
        }

        // 验证新密码是否符合强度要求
        if (!isPasswordStrong(userResetPassword.getNewPassword())) {
            log.error("密码不符合强度要求: {}", userResetPassword.getNewPassword());
            throw new ServiceException(StatusCode.VALIDATED_ERROR);
        }

        // 更新用户的新密码
        user.setPassword(userResetPassword.getNewPassword());

        try {
            // 更新用户信息到数据库
            userMapper.updateUser(user);
            log.info("密码重置成功: {}", userResetPassword.getPhone());
        } catch (Exception e) {
            // 记录更新失败的日志
            log.error("密码重置失败: {}", userResetPassword.getPhone(), e);
            throw new ServiceException(StatusCode.PASSWORD_RESET_FAILED);
        }
    }

    /**
     * 检查密码是否符合强度要求
     *
     * @param password 待检查的密码
     * @return 如果密码符合强度要求返回true，否则返回false
     */
    private boolean isPasswordStrong(String password) {
        // 密码长度至少为8个字符
        if (password.length() < 8) {
            log.error("密码长度不足8个字符: {}", password);
            return false;
        }

        // 密码必须包含至少一个大写字母
        if (!Pattern.compile("[A-Z]").matcher(password).find()) {
            log.error("密码必须包含至少一个大写字母: {}", password);
            return false;
        }

        // 密码必须包含至少一个小写字母
        if (!Pattern.compile("[a-z]").matcher(password).find()) {
            log.error("密码必须包含至少一个小写字母: {}", password);
            return false;
        }

        // 密码必须包含至少一个数字
        if (!Pattern.compile("[0-9]").matcher(password).find()) {
            log.error("密码必须包含至少一个数字: {}", password);
            return false;
        }

        return true;
    }


    @Override
    public UserVO phoneLogin(UserPhoneLoginParam userPhoneLoginParam, HttpSession session) {
        log.debug("开始处理用户手机号登录请求: userPhoneLoginParam={}", userPhoneLoginParam);
        // 获取手机号和验证码
        String phone = userPhoneLoginParam.getPhone();
        String code = userPhoneLoginParam.getCaptcha();

        // 根据手机号查询用户信息
        UserVO userVO = userMapper.queryUserByPhone(phone);
        // 如果用户不存在，记录警告日志并抛出用户不存在异常
        if (userVO == null) {
            log.warn("用户不存在: {}", phone);
            throw new ServiceException(StatusCode.USER_NOT_EXIST);
        }

        // 验证验证码
        String key = "captcha:" + phone;
        String storedCode = redisTemplate.opsForValue().get(key);
        // 如果验证码不存在或不匹配，记录警告日志并抛出验证码错误异常
        if (storedCode == null || !code.equals(storedCode)) {
            log.warn("验证码错误或已过期: {}", phone);
            throw new ServiceException(StatusCode.CAPTCHA_ERROR);
        }

        // 清除已使用的验证码
        redisTemplate.delete(key);

        // 将用户信息保存到会话中
        session.setAttribute("user", userVO);

        log.debug("用户登录成功: {}", phone);
        return userVO;
    }

    /**
     * 生成并存入Redis的验证码
     *
     * @param phone 手机号
     * @return 生成的验证码
     */
    public String generateAndStoreCaptcha(String phone) {
        log.debug("开始生成验证码: phone={}", phone);

        // 生成4位随机验证码
        Random random = new SecureRandom(); // 使用更安全的随机数生成器
        String captcha = String.format("%04d", random.nextInt(10000));

        // 存入Redis，设置过期时间为5分钟
        String key = "captcha:" + phone;
        redisTemplate.opsForValue().set(key, captcha, 5, TimeUnit.MINUTES);

        log.debug("验证码生成成功并存储: phone={}, captcha={}", phone, captcha);

        return captcha;
    }
}
